#ifndef _MAT44_HPP
#define _MAT44_HPP

//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <stdio.h>
#include <Math/Vector.hpp>

//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
#define M44(m, r, c) m[(c)*4 + (r)]

	class Matrix {
	public:	
		// Type definition		
		typedef float Matrix4[16];
		
		// a= b
		static void Copy4(float *a, const float *b);
		// a= 0
		static void Zero4(float *a);
		// a= Id
		static void Identity4(float *a);
		// a= Id[3x3]
		static void Identity3(float *a);
		// a= b * c
		static void Mul4(float *a, const float *b, const float *c);
		// a= k * b
		static void ConstMul4(float *a, float k, const float *b);
		// a= a * b
		static void Compose4(float *a, const float *b);
		// v= a * u
		static void MulVec4(float *v, const float *a, const float *u);
		// u = a * u 
		static void ComposePoint4(const float *a, float *u);
		// u = a * u with "u" direction u[3]= 0
		static void ComposeVector4(const float *a, float *u);
		// a= u * u^T
		static void InitVec4Tranpose4(float *a, const float *v);
		static void InitVec3Tranpose4(float *a, const float *v);
		// a= b - c 
		static void Sub4(float *a, const float *b, const float *c);
		// a= b + c 
		static void Add4(float *a, const float *b, const float *c);
		// a= inverse(b) 
		static int Inverse4(float *inverse, const float *src);
		// Display matrix
		static void Print4(const float *a);
		// Construct scaling matrix
		static void Scale4(float *a, float x, float y, float z);
		// Construct translation matrix
		static void Translate4(float *a, float x, float y, float z);
		// Construct point of view matrix
		static void Rotate4(float *a, float angle, float x, float y, float z);
		// Construct point of view matrix
		static void LookAt4(float *a, const float *eye, const float *center, const float *up);
		// Construct perspective matrix
		static void Frustum4(float *a, float left, float right, float bottom, float top, float near, float far);
		// Construct perspective matrix
		static void Perspective4(float *a, float fovy, float aspect, float near, float far);		
		// Construct perspective matrix with a linear Z
		static void LinearPerspective4(float *a, float fovy, float aspect, float near, float far);
		
		static const Matrix4 Identity;
	private:
		static Matrix4 identityMatrix4;
	};
#endif

